package base.service.impl;

import base.bean.Seckill;
import base.bean.SuccessKilled;
import base.bean.dto.Exposer;
import base.bean.dto.SeckillExecution;
import base.bean.exception.RepeatKillException;
import base.bean.exception.SeckillCloseException;
import base.bean.exception.SeckillException;
import base.dao.SeckillDao;
import base.dao.SuccessKilledDao;
import base.enums.SeckillStatEnum;
import base.service.SeckillService;
import com.sun.org.apache.regexp.internal.RE;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.util.Date;
import java.util.List;

/**
 * Created by 30509 on 2018/3/25.
 */
@Service
public class SeckillServiceImpl implements SeckillService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private SeckillDao seckillDao;
    @Autowired
    private SuccessKilledDao successKilledDao;
    //md5盐值支字符串，用于混淆MD5
    private final String slat="sdsafeqsbtguytgfdbfdfd2134@!#@!$";
    @Override
    public List<Seckill> getSeckillList() {
        return seckillDao.queryAll(0, 4);
    }

    @Override
    public Seckill getById(long seckillId) {
        return seckillDao.queryById(seckillId);
    }

    @Override
    public Exposer exportSeckillUrl(long seckillId) {
        Seckill seckill = seckillDao.queryById(seckillId);
        if (seckill == null) {
            return new Exposer(false, seckillId);
        }
        Date startTime = seckill.getStartTime();
        Date endTime = seckill.getEndTime();

        Date nowTime = new Date();
        if (nowTime.getTime() < startTime.getTime() || nowTime.getTime() > endTime.getTime()) {
            return new Exposer(false, seckillId, nowTime.getTime(), startTime.getTime(), endTime.getTime());
        }
        //转化特定字符串的过程
        String md5 = getMD5(seckillId);
        return new Exposer(true, md5, seckillId);
    }

    private String getMD5(long seckillId) {
        String base = seckillId + "/" + slat;
        String md5 = DigestUtils.md5DigestAsHex(base.getBytes());
        return md5;
    }
    @Override
    @Transactional
    public SeckillExecution executeSeckill(long seckillId, long userPhone, String md5) throws SeckillException, RepeatKillException, SeckillException {
       if(md5 == null  || !md5.equals(getMD5(seckillId))){
           throw new SeckillException("地址被恶意改了！");
           }
        Date nowTime = new Date();
        try{
            //秒杀成功！
       int updateCount = seckillDao.reduceNumber(seckillId,nowTime);
        if(updateCount <= 0){
            //没有更新到记录
            throw new SeckillCloseException("秒杀结束了！");
        }else{
            //记录购买行为
            int insertCount = successKilledDao.insertSuccessKilled(seckillId, userPhone);
            if(insertCount <= 0){
                //重复秒杀
                throw new RepeatKillException("重复秒杀！");
            }else{
                //秒杀成功！
                SuccessKilled successKilled = successKilledDao.queryByIdWithSeckill(seckillId, userPhone);
                return new SeckillExecution(seckillId, successKilled, SeckillStatEnum.SUCCESS);
            }
        }
        } catch (SeckillCloseException e1) {
            throw e1;
        } catch (RepeatKillException e2) {
            throw e2;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            //所有编译期异常，转化为运行期异常。
            throw new SeckillException("内部异常！;" + e.getMessage());
        }
    }
}
